home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / python-support / gnome-games-data / gnome_sudoku / saver.py < prev    next >
Encoding:
Python Source  |  2009-04-14  |  8.0 KB  |  233 lines

  1. # -*- coding: utf-8 -*-
  2. import pickle, types, os, os.path, sudoku, errno
  3. from defaults import *
  4. from gtk_goodies.dialog_extras import show_message
  5. from gettext import gettext as _
  6.  
  7. SAVE_ATTRIBUTES = [('gsd.hints'),
  8.                    ('gsd.impossible_hints'),
  9.                    ('gsd.auto_fills'),
  10.                    ('timer.__absolute_start_time__'),
  11.                    ('timer.tot_time'),
  12.                    ('timer.tot_time_complete'),
  13.                    ]
  14.  
  15. def super_getattr (obj, attr):
  16.     """getattr, following the dots."""
  17.     attrs=attr.split('.')
  18.     for a in attrs:
  19.         obj = getattr(obj,a)
  20.     return obj
  21.  
  22. def super_setattr (obj, attr, val):
  23.     """setattr, following the dots."""
  24.     attrs = attr.split('.')
  25.     if len(attrs) > 1:
  26.         sub_attrs = attrs[0:-1]
  27.         attr = attrs[-1]
  28.         for a in sub_attrs:
  29.             obj = getattr(obj,a)
  30.     setattr(obj,attr,val)
  31.  
  32. def jar_game (ui):
  33.     jar = {} # what we will pickle
  34.     ui.timer.finish_timing()
  35.     jar['game']=ui.gsd.grid.to_string()
  36.     jar['trackers']=ui.gsd.trackers
  37.     jar['tracking']=ui.gsd.__trackers_tracking__
  38.     jar['notes']=[]
  39.     for e in ui.gsd.__entries__.values():
  40.         top,bot = e.get_note_text()
  41.         if top or bot:
  42.             jar['notes'].append((e.x,e.y,top,bot))
  43.     for attr in SAVE_ATTRIBUTES:
  44.         jar[attr]=super_getattr(ui,attr)
  45.     return jar
  46.  
  47. def open_game (ui, jar):
  48.     ui.gsd.load_game(jar['game'])
  49.     # this is a bit easily breakable... we take advantage of the fact
  50.     # that we create tracker IDs sequentially and that {}.items()
  51.     # sorts by keys by default
  52.     for tracker,tracked in jar.get('trackers',{}).items():
  53.         # add 1 tracker per existing tracker...
  54.         ui.tracker_ui.add_tracker()
  55.         for x,y,val in tracked:
  56.             ui.gsd.add_tracker(x,y,tracker,val=val)
  57.     for tracker,tracking in jar.get('tracking',{}).items():
  58.         if tracking:
  59.             ui.tracker_ui.select_tracker(tracker)
  60.     for attr in SAVE_ATTRIBUTES:
  61.         super_setattr(ui,attr,jar.get(attr,None))
  62.     for attr in SAVE_ATTRIBUTES:
  63.         if jar.get(attr,None) == None:
  64.             super_setattr(ui,attr,0)
  65.     if jar.has_key('notes') and jar['notes']:
  66.         for x,y,top,bot in jar['notes']:
  67.             ui.gsd.__entries__[(x,y)].set_note_text(top,bot)
  68.         
  69. def pickle_game (ui, target):
  70.     close_me = False
  71.     if type(target) in types.StringTypes:
  72.         target = file(target,'w')
  73.         close_me = True
  74.     to_dump = jar_game(ui)
  75.     pickle.dump(to_dump,target)
  76.     if close_me: target.close()
  77.     
  78. def unpickle_game (ui, target):
  79.     close_me = False
  80.     if type(target)==str:
  81.         target = file(target, 'r')
  82.         close_me = True
  83.     open_game(ui,pickle.load(target))
  84.     if close_me: target.close()
  85.  
  86. class SudokuTracker:
  87.  
  88.     """A class to track games in progress and games completed.
  89.     """
  90.  
  91.     def __init__ (self):
  92.         self.save_path = os.path.expanduser('~/.sudoku/saved')
  93.         self.finished_path = os.path.expanduser('~/.sudoku/finished')
  94.         self.create_dir_safely(self.save_path)
  95.         self.create_dir_safely(self.finished_path)
  96.  
  97.     def create_dir_safely (self, path):
  98.         if not os.path.exists(path):
  99.             try:
  100.                 os.makedirs(path)
  101.             except OSError, e:                
  102.                 if e.errno == errno.ENOSPC:
  103.                     show_message(
  104.                         title=_('No Space'),
  105.                         label=_('No space left on disk'),
  106.                         message_type=gtk.MESSAGE_ERROR,
  107.                         sublabel=_('Sudoku is unable to created data folder %(path)s.')%locals() +\
  108.                                  _('There is no disk space left!')
  109.                         )
  110.                 else:
  111.                     show_message(
  112.                         title='Error creating directory',
  113.                         label='Error creating directory',
  114.                         sublabel=_('Sudoku was unable to create data folder %(path)s.')%locals() +\
  115.                         _('Error %(errno)s: %(error)s')%{'errno':e.errno,
  116.                                                          'error':e.strerror}
  117.                         )
  118.                         
  119.     def game_from_ui (self, ui):
  120.         return ui.gsd.grid.virgin.to_string()
  121.  
  122.     def get_filename (self, gamestring):
  123.         return gamestring.split('\n')[0].replace(' ','')
  124.  
  125.     def save_game (self, ui):
  126.         game = self.game_from_ui(ui)
  127.         jar = jar_game(ui)
  128.         filename = os.path.join(self.save_path,self.get_filename(jar['game']))
  129.         try:
  130.             outfi = file(filename,'w')
  131.             pickle.dump(jar,outfi)
  132.             outfi.close()
  133.         except (OSError, IOError), e:
  134.             show_message(
  135.                 title=_('Sudoku unable to save game.'),
  136.                 label=_('Sudoku unable to save game.'),
  137.                 message_type=gtk.MESSAGE_ERROR,
  138.                 sublabel=(_('Unable to save file %(filename)s.')%locals()
  139.                           + '\n' +
  140.                           _('Error %(errno)s: %(error)s')%{
  141.                 'errno':e.errno,
  142.                 'error':e.strerror
  143.                 })
  144.                 )
  145.  
  146.     def finish_game (self, ui):
  147.         game = self.game_from_ui(ui)
  148.         jar  = jar_game(ui)
  149.         self.finish_jar(jar)
  150.  
  151.     def finish_jar (self, jar):
  152.         self.remove_from_saved_games(jar)
  153.         try:
  154.             filename = os.path.join(self.finished_path,
  155.                                     self.get_filename(jar['game']))
  156.             outfi = file(filename,'w')
  157.             pickle.dump(jar,outfi)
  158.             outfi.close()
  159.         except (OSError, IOError), e:
  160.             show_message(
  161.                 title=_('Sudoku unable to mark game as finished.'),
  162.                 label=_('Sudoku unable to mark game as finished.'),
  163.                 message_type=gtk.MESSAGE_ERROR,
  164.                 sublabel=(_('Unable to save file %(filename)s.')%locals() + '\n' +
  165.                           _('Error %(errno)s: %(error)s')%{
  166.                 'errno':e.errno,
  167.                 'error':e.strerror
  168.                 })
  169.                 )
  170.         try:
  171.             filename = list_of_finished_games = os.path.join(
  172.                 os.path.join(DATA_DIR,'puzzles'),'finished'
  173.                 )
  174.             ofi = open(list_of_finished_games,'a')
  175.             ofi.write(jar['game'].split('\n')[0]+'\n')
  176.             ofi.close()
  177.         except (OSError, IOError), e:
  178.             show_message(
  179.                 title=_('Sudoku unable to mark game as finished.'),
  180.                 label=_('Sudoku unable to mark game as finished.'),
  181.                 message_type=gtk.MESSAGE_ERROR,
  182.                 sublabel=(_('Unable to save file %(filename)s.')%locals() + '\n' +
  183.                           _('Error %(errno)s: %(error)s')%{
  184.                 'errno':e.errno,
  185.                 'error':e.strerror
  186.                 })
  187.                 )
  188.  
  189.     def remove_from_saved_games (self, jar):
  190.         previously_saved_game = os.path.join(
  191.             self.save_path,self.get_filename(jar['game'])
  192.             )
  193.         if os.path.exists(previously_saved_game):
  194.             os.remove(os.path.join(previously_saved_game))
  195.  
  196.     def abandon_game (self, ui):
  197.         game = self.game_from_ui(ui)
  198.         jar  = jar_game(ui)
  199.         self.remove_from_saved_games(jar)
  200.         
  201.     def list_saved_games (self):
  202.         try:
  203.             files = os.listdir(self.save_path)
  204.         except OSError, e:
  205.             files = []
  206.         games = []
  207.         for f in files:
  208.             f = os.path.join(self.save_path,f)
  209.             try:
  210.                 jar = pickle.load(file(f,'r'))
  211.             except:
  212.                 print 'Warning: could not read file',f
  213.             else:
  214.                 if self.is_valid(jar):
  215.                     jar['saved_at']=os.stat(f)[8]
  216.                     games.append(jar)
  217.                 else:
  218.                     print 'Warning: malformed save game',f
  219.         return games
  220.  
  221.     def is_valid (self, jar):
  222.         virgin = jar['game'].split('\n')[0].replace(' ','')
  223.         played = jar['game'].split('\n')[1].replace(' ','')
  224.  
  225.         if len(virgin) != 81 or len(played) != 81:
  226.             return False
  227.  
  228.         if not virgin.isdigit() or not played.isdigit():
  229.             return False
  230.  
  231.         return True
  232.  
  233.